<template>
  <view class="mask flex-center">
    <view class="content">
      <view class="content-top">
        <text class="content-top-text">发现新版本</text>
        <image class="content-top" style="top: 0" width="100%" height="100%" src="@/static/images/bg_top.png"></image>
      </view>
      <view class="content-header"></view>
      <view class="content-body">
        <view class="title">
          <text>v{{ version }}</text>
        </view>
        <view class="body">
          <scroll-view class="box-des-scroll" scroll-y="true">
            <text class="box-des">
              {{ description }}
            </text>
          </scroll-view>
        </view>
        <view class="footer flex-center">
          <template v-if="!downloadSuccess">
            <view class="progress-box flex-column" v-if="downloading">
              <view class="progress-wrap">
                <view class="progress-line" :style="{ width: `${downLoadPercent < 10 ? 10 : downLoadPercent}%` }">
                  <view class="progress-percent"> {{ downLoadPercent }}% </view>
                </view>
              </view>
              <view class="progress-tip">
                <text>努力更新中</text>
              </view>
            </view>

            <button v-else class="content-button" style="border: none; color: #fff" plain @click="updateApp">
              {{ downLoadBtnText }}
            </button>
          </template>

          <button
            v-else-if="downloadSuccess && !installed"
            class="content-button"
            style="border: none; color: #fff"
            plain
            :loading="installing"
            :disabled="installing"
            @click="installPackage"
          >
            {{ installing ? '正在安装……' : '下载完成，立即安装' }}
          </button>

          <button v-if="installed" class="content-button" style="border: none; color: #fff" plain @click="restart">
            安装完毕，点击重启
          </button>
        </view>
      </view>
      <image v-if="!is_mandatory" class="close-img" src="/static/images/app_update_close.png" @click.stop="closeUpdate">
      </image>
    </view>
  </view>
</template>

<script>
const localFilePathKey = 'UNI_ADMIN_UPGRADE_CENTER_LOCAL_FILE_PATH'
let downloadTask = null
let openSchemePromise
/**
 * 对比版本号，如需要，请自行修改判断规则
 * 支持比对	("3.0.0.0.0.1.0.1", "3.0.0.0.0.1")	("3.0.0.1", "3.0")	("3.1.1", "3.1.1.1") 之类的
 * @param {Object} v1
 * @param {Object} v2
 * v1 > v2 return 1
 * v1 < v2 return -1
 * v1 == v2 return 0
 */
function compare(v1 = '0', v2 = '0') {
  v1 = String(v1).split('.')
  v2 = String(v2).split('.')
  const minVersionLens = Math.min(v1.length, v2.length)

  let result = 0
  for (let i = 0; i < minVersionLens; i++) {
    const curV1 = Number(v1[i])
    const curV2 = Number(v2[i])

    if (curV1 > curV2) {
      result = 1
      break
    } else if (curV1 < curV2) {
      result = -1
      break
    }
  }

  if (result === 0 && v1.length !== v2.length) {
    const v1BiggerThenv2 = v1.length > v2.length
    const maxLensVersion = v1BiggerThenv2 ? v1 : v2
    for (let i = minVersionLens; i < maxLensVersion.length; i++) {
      const curVersion = Number(maxLensVersion[i])
      if (curVersion > 0) {
        v1BiggerThenv2 ? (result = 1) : (result = -1)
        break
      }
    }
  }

  return result
}

export default {
  data() {
    return {
      localPackageInfo: {},
      // 从之前下载安装
      installForBeforeFilePath: '',

      // 安装
      installed: false,
      installing: false,

      // 下载
      downloadSuccess: false,
      downloading: false,

      downLoadPercent: 0,
      downloadedSize: 0,
      packageFileSize: 0,

      tempFilePath: '', // 要安装的本地包地址

      // 默认安装包信息
      title: '更新日志',
      contents: '',
      is_mandatory: true, // 是否强制更新

      // 可自定义属性
      subTitle: '发现新版本',
      downLoadBtnText: '立即更新',
      downLoadingText: '安装包下载中，请稍后'
    }
  },
  onLoad({ key }) {
    if (!key) {
      console.error('key为空，请检查后重试')
      uni.navigateBack()
      return
    }

    const localPackageInfo = uni.getStorageSync(key)
    if (!localPackageInfo) {
      console.error('安装包信息为空，请检查后重试')
      uni.navigateBack()
      return
    }

    this.is_mandatory = localPackageInfo.updateForce
    console.log('localPackageInfo.updateForce', localPackageInfo.updateForce)

    const requiredKey = ['version', 'url']
    for (const key in localPackageInfo) {
      if (requiredKey.indexOf(key) !== -1 && !localPackageInfo[key]) {
        console.error(`参数 ${key} 必填，请检查后重试`)
        uni.navigateBack()
        return
      }
    }

    Object.assign(this, localPackageInfo)
    this.checkLocalStoragePackage()
  },
  onBackPress() {
    // 强制更新不允许返回
    if (this.is_mandatory) {
      return true
    }

    downloadTask && downloadTask.abort()
  },
  onHide() {
    openSchemePromise = null
  },
  methods: {
    checkLocalStoragePackage() {
      // 如果已经有下载好的包，则直接提示安装
      const localFilePathRecord = uni.getStorageSync(localFilePathKey)
      if (localFilePathRecord) {
        const { version, savedFilePath, installed } = localFilePathRecord

        // 比对版本
        if (!installed && compare(version, this.version) === 0) {
          this.downloadSuccess = true
          this.installForBeforeFilePath = savedFilePath
          this.tempFilePath = savedFilePath
        } else {
          // 如果保存的包版本小 或 已安装过，则直接删除
          this.deleteSavedFile(savedFilePath)
        }
      }
    },
    async closeUpdate() {
      if (this.downloading) {
        if (this.is_mandatory) {
          return uni.showToast({
            title: '下载中，请稍后……',
            icon: 'none',
            duration: 500
          })
        }
        uni.showModal({
          title: '是否取消下载？',
          cancelText: '否',
          confirmText: '是',
          success: (res) => {
            if (res.confirm) {
              downloadTask && downloadTask.abort()
              uni.navigateBack()
            }
          }
        })
        return
      }

      if (this.downloadSuccess && this.tempFilePath) {
        // 包已经下载完毕，稍后安装，将包保存在本地
        await this.saveFile(this.tempFilePath, this.version)
        uni.switchTab({
          url: '/pages/messages/index'
        })
        return
      }

      uni.switchTab({
        url: '/pages/messages/index'
      })
    },
    updateApp() {
      this.checkStoreScheme().catch(() => {
        this.downloadPackage()
      })
    },
    // 跳转应用商店
    checkStoreScheme() {
      const storeList = (this.store_list || []).filter((item) => item.enable)
      if (storeList && storeList.length) {
        storeList
          .sort((cur, next) => next.priority - cur.priority)
          .map((item) => item.scheme)
          .reduce((promise, cur, curIndex) => {
            openSchemePromise = (promise || (promise = Promise.reject())).catch(() => {
              return new Promise((resolve, reject) => {
                plus.runtime.openURL(cur, (err) => {
                  reject(err)
                })
              })
            })
            return openSchemePromise
          }, openSchemePromise)
        return openSchemePromise
      }

      return Promise.reject()
    },
    downloadPackage() {
      this.downloading = true

      // 下载包
      downloadTask = uni.downloadFile({
        url: this.url,
        success: (res) => {
          if (res.statusCode == 200) {
            this.downloadSuccess = true
            this.tempFilePath = res.tempFilePath

            // 强制更新，直接安装
            if (this.is_mandatory) {
              this.installPackage()
            }
          }
        },
        complete: () => {
          this.downloading = false

          this.downLoadPercent = 0
          this.downloadedSize = 0
          this.packageFileSize = 0

          downloadTask = null
        }
      })

      downloadTask.onProgressUpdate((res) => {
        this.downLoadPercent = res.progress
        this.downloadedSize = (res.totalBytesWritten / Math.pow(1024, 2)).toFixed(2)
        this.packageFileSize = (res.totalBytesExpectedToWrite / Math.pow(1024, 2)).toFixed(2)
      })
    },
    installPackage() {
      // #ifdef APP-PLUS
      plus.runtime.install(this.tempFilePath)
      // #endif
    },
    restart() {
      this.installed = false
      // #ifdef APP-PLUS
      // 更新完重启app
      plus.runtime.restart()
      // #endif
    },
    saveFile(tempFilePath, version) {
      return new Promise((resolve, reject) => {
        uni.saveFile({
          tempFilePath,
          success({ savedFilePath }) {
            uni.setStorageSync(localFilePathKey, {
              version,
              savedFilePath
            })
          },
          complete() {
            resolve()
          }
        })
      })
    },
    deleteSavedFile(filePath) {
      uni.removeStorageSync(localFilePathKey)
      return uni.removeSavedFile({
        filePath
      })
    },
    jumpToAppStore() {
      // #ifdef APP-PLUS
      plus.runtime.openURL(this.url)

      // #endif
    }
  }
}
</script>

<style lang="scss" scoped>
$cu-color-primary: #2ac0c8;

.flex-center {
  /* #ifndef APP-NVUE */
  display: flex;
  /* #endif */
  justify-content: center;
  align-items: center;
}

.mask {
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.65);
}

.content-header {
  height: 70rpx;
}
.content {
  position: relative;
  top: 0;
  width: 325px;
  background-color: #fff;
  box-sizing: border-box;
  border-radius: 20rpx;
}

.text {
  /* #ifndef APP-NVUE */
  display: block;
  /* #endif */
  line-height: 200px;
  text-align: center;
  color: #ffffff;
}

.content-top {
  position: absolute;
  top: -195rpx;
  left: 0;
  width: 325px;
  height: 150px;
}

.content-top-text {
  position: absolute;
  top: 120px;
  left: 25px;
  z-index: 1;
  font-size: 21px;
  font-family: PingFang SC-Medium, PingFang SC;
  font-weight: 500;
  color: #333333;
}

.content-body {
  padding: 0 25px;
  background: #fff;
  .title {
    font-size: 15px;
    font-family: PingFang SC-Regular, PingFang SC;
    font-weight: 400;
    color: #b2b2b2;
    line-height: 21px;
    margin-top: 6px;
  }
}

.footer {
  height: 70px;
  display: flex;
  align-items: flex-start;
  justify-content: space-around;
}

.box-des-scroll {
  padding: 15px 0 20px 0;
  height: 120px;
  box-sizing: border-box;
  text-align: left;
}

.box-des {
  font-size: 14px;
  color: #333333;
  line-height: 20px;
}

.progress-box {
  width: 100%;

  .progress-wrap {
    width: 100%;
    height: 12px;
    border-radius: 6px;
    background: #f8f8f8;
    position: relative;

    .progress-line {
      position: absolute;
      border-radius: 6px;
      height: 12px;
      background: $cu-color-primary;
      text-align: right;
      transition: all 0.1s;
    }

    .progress-percent {
      position: absolute;
      top: 50%;
      z-index: 1;
      right: 0;
      height: 17px;
      line-height: 17px;
      font-size: 12px;
      color: #fff;
      transform: translateY(-50%);
      padding-right: 5px;
    }
  }

  .progress-tip {
    margin-top: 13px;
    text-align: center;
    font-size: 14px;
    color: #b2b2b2;
    line-height: 25px;
  }
}

.progress {
  width: 90%;
  height: 40rpx;
  border-radius: 35px;
}

.close-img {
  width: 70rpx;
  height: 70rpx;
  z-index: 1000;
  position: absolute;
  bottom: -120rpx;
  left: calc(50% - 70rpx / 2);
}

.content-button {
  text-align: center;
  flex: 1;
  font-size: 18px;
  font-weight: 400;
  color: #ffffff;
  border-radius: 24px;
  height: 49px;
  line-height: 49px;
  background: $cu-color-primary;
}

.flex-column {
  display: flex;
  flex-direction: column;
  align-items: center;
}
</style>
